import pandas as pd
import math
import os
import re
from config import AppConfig

class ProcessData:
    def __init__(self, config):
        self.config = config
        
    def process_file(self, file_path):
        """处理单个测量文件的核心方法"""
        # 初始化数据结构
        self._init_data_structures()
    
        # 读取并解析文件
        self._read_and_parse_file(file_path)
        
        # 数据验证
        self._validate_data()
        # 处理FIX点筛选
        self._process_fix_point_screening()
        
        # 内插FIX点数据
        self._interpolate_fix_points()
        
        # 处理加点数据
        self._process_add_points()
        
        # 处理改点数据
        self._process_change_points()
        
        # 处理删点数据
        self._process_delete_points()
        # print("处理模块",self.config.ZZFIX[self.config.dmnum])
        return self._prepare_output()

    def _init_data_structures(self):
        """初始化数据结构（与原始代码完全一致）"""
        dmnum = self.config.dmnum
        
        self.config.line_numbers[dmnum] = []
        self.config.EC1[dmnum] = []
        self.config.fix[dmnum] = []
        self.config.add[dmnum] = []
        self.config.ysdel[dmnum] = []
        self.config.POS[dmnum] = []
        self.config.FIX[dmnum] = []
        self.config.FIX[dmnum] = []
        self.config.ADD[dmnum] = []
        self.config.CHA[dmnum] = []
        self.config.XH[dmnum] = []
        
        self.config.dfEC1[dmnum] = pd.DataFrame()
        self.config.dfFIX[dmnum] = pd.DataFrame()
        self.config.ZZFIX[dmnum] = pd.DataFrame()
        self.config.dfADD[dmnum] = pd.DataFrame()
        self.config.dfDEL[dmnum] = pd.DataFrame()
        self.config.dfCHA[dmnum] = pd.DataFrame()
        self.config.ys_ZZFIX[dmnum] = pd.DataFrame()
        #用于检查的单波束完整点数据结构
        self.config.single_beam_data[dmnum] = []
       
       
    def _read_and_parse_file(self, file_path):
        """读取并解析文件，使用传入的file_path参数"""
        dmnum = self.config.dmnum
        print(f"正在处理文件: {file_path}")
        
        with open(file_path, 'r') as note:
            date_regex = re.compile(r'\bTND.+')
            location_regex = re.compile(r'\bPTS\s.+')
            fix_regex = re.compile(r"\bFIX .+")
            ec1_regex = re.compile(r"\bEC1 1.+")
            pos_regex = re.compile(r"\bPOS .+")
            add_regex = re.compile(r"\bAdd.+")
            cha_regex = re.compile(r"\bCha.+")
            del_regex = re.compile(r"\bDel.+")

            for line in note:
                if date_regex.search(line):
                    date_fields = date_regex.search(line).group().split()
                    self.config.line_numbers[dmnum].append(date_fields[2])
                
                if location_regex.search(line):
                    location_fields = location_regex.search(line).group().split()
                    self.config.line_numbers[dmnum].append(location_fields[1])
                    self.config.line_numbers[dmnum].append(location_fields[2])
                
                if fix_regex.findall(line):
                    fix_fields = fix_regex.findall(line)[0].split(" ")
                    fix_fields[2] = round(float(fix_fields[2]), 3)
                    fix_fields[3] = int(fix_fields[3])
                    result = [fix_fields[2], fix_fields[3]]
                    self.config.fix[dmnum].append(result)
                
                if ec1_regex.findall(line):
                    ec1_fields = ec1_regex.findall(line)[0].split(" ")
                    ec1_fields[2] = round(float(ec1_fields[2]), 3)  #时间  过午夜零点的秒数
                    ec1_fields[3] = '-' + ec1_fields[3]
                    ec1_fields[3] = round(float(ec1_fields[3]), 2)  #水深
                    result = [ec1_fields[2], ec1_fields[3]]
                    self.config.EC1[dmnum].append(result)
                
                if pos_regex.findall(line):
                    pos_fields = pos_regex.findall(line)[0].split(" ")
                    pos_fields[2] = round(float(pos_fields[2]), 3)   #时间  过午夜零点的秒数
                    pos_fields[3] = round(float(pos_fields[3]), 3)   #E
                    pos_fields[4] = round(float(pos_fields[4]), 3)   #N
                    result = [pos_fields[2], pos_fields[3], pos_fields[4]]
                    self.config.POS[dmnum].append(result)
                
                if add_regex.findall(line):
                    add_fields = add_regex.findall(line)[0].split(" ")
                    add_fields[1] = int(add_fields[1])
                    add_fields[2] = round(float(add_fields[2]), 3)
                    result = [add_fields[2], add_fields[1]]
                    self.config.add[dmnum].append(result)
                
                if cha_regex.findall(line):
                    cha_fields = cha_regex.findall(line)[0].split(" ")
                    cha_fields[1] = int(cha_fields[1])
                    cha_fields[2] = float(cha_fields[2])
                    cha_fields[3] = -float(cha_fields[3])
                    cha_fields[4] = -float(cha_fields[4])
                    result = [cha_fields[2], cha_fields[1], cha_fields[3], cha_fields[4]]
                    self.config.CHA[dmnum].append(result)
                
                if del_regex.findall(line):
                    del_fields = del_regex.findall(line)[0].split(" ")
                    del_fields[1] = int(del_fields[1])
                    del_fields[2] = round(float(del_fields[2]), 3)
                    result = [del_fields[2], del_fields[1]]
                    self.config.ysdel[dmnum].append(result)

    def _validate_data(self):
        """数据验证（与原始代码完全一致）"""
        dmnum = self.config.dmnum
        
        if len(self.config.EC1[dmnum]) == 0:
            tkinter.messagebox.showwarning('警告', f'{self.config.notemenu[dmnum]} config.EC1 1 数据为空!')
        
        if len(self.config.POS[dmnum]) == 0:
            tkinter.messagebox.showwarning('警告', f'{self.config.notemenu[dmnum]}pos 数据为空!')
        
        if len(self.config.fix[dmnum]) == 0:
            tkinter.messagebox.showwarning('警告', f'{self.config.notemenu[dmnum]}config.FIX  数据为空!')

    def _process_fix_point_screening(self):
        """处理FIX点筛选（与原始代码完全一致）"""
        dmnum = self.config.dmnum
        
        if self.config.scrpoint > 0:
            new_fix = []
            new_fix.append(self.config.fix[dmnum][0])
            
            # 获取第一个FIX点的坐标
            e1 = 0
            n1 = 0
            for k in range(1, len(self.config.POS[dmnum])):
                # 如果config.fix数前没有config.POS数据，就用最近config.POS的坐标
                if self.config.fix[dmnum][0][0] <= self.config.POS[dmnum][0][0]:
                    e1 = self.config.POS[dmnum][0][1]
                    n1 = self.config.POS[dmnum][0][2]
                # 如果config.fix数据后没有config.POS数据，就用最近config.POS的坐标
                elif self.config.fix[dmnum][0][0] >= self.config.POS[dmnum][len(self.config.POS[dmnum]) - 1][0]:
                    e1 = self.config.POS[dmnum][len(self.config.POS[dmnum]) - 1][1]
                    n1 = self.config.POS[dmnum][len(self.config.POS[dmnum]) - 1][2]
                elif (self.config.fix[dmnum][0][0] >= self.config.POS[dmnum][k - 1][0]) & (
                        self.config.fix[dmnum][0][0] <= self.config.POS[dmnum][k][0]):
                    t = self.config.POS[dmnum][k][0] - self.config.POS[dmnum][k - 1][0]
                    t1 = self.config.fix[dmnum][0][0] - self.config.POS[dmnum][k - 1][0]
                    e1 = round((t1 / t) * (self.config.POS[dmnum][k][1] - self.config.POS[dmnum][k - 1][1]) + self.config.POS[dmnum][k - 1][1], 3)
                    n1 = round((t1 / t) * (self.config.POS[dmnum][k][2] - self.config.POS[dmnum][k - 1][2]) + self.config.POS[dmnum][k - 1][2], 3)
            
            fxh = self.config.fix[dmnum][1][1] # 筛选后点序号,接原第一点的序号
            for i in range(1, len(self.config.POS[dmnum])):
                if (self.config.scrpoint >= math.sqrt((e1 - self.config.POS[dmnum][i - 1][1]) ** 2 + (n1 - self.config.POS[dmnum][i - 1][2]) ** 2)) & (
                        math.sqrt((e1 - self.config.POS[dmnum][i][1]) ** 2 + (n1 - self.config.POS[dmnum][i][2]) ** 2) >= self.config.scrpoint):
                    # 筛选后点序号,接原第一点的序号
                    result = [round((self.config.POS[dmnum][i - 1][0] + self.config.POS[dmnum][i][0]) / 2, 3), fxh] # 时间，序号
                    fxh += 1
                    new_fix.append(result)
                    e1 = self.config.POS[dmnum][i][1]
                    n1 = self.config.POS[dmnum][i][2]
            
            new_fix.append(self.config.fix[dmnum][len(self.config.fix[dmnum]) - 1])
            self.config.fix[dmnum] = new_fix
            
    def _interpolate_fix_points(self):
        """内插FIX点数据（与原始代码完全一致）"""
        dmnum = self.config.dmnum
        
        for i in range(len(self.config.fix[dmnum])):
            # 处理水深
            if len(self.config.EC1[dmnum]) == 0:
                ft = self.config.fix[dmnum][i][0]
                fxh = int(self.config.fix[dmnum][i][1])
                fz = 0

            else:
                #如果config.fix数据前没有config.EC1 1数据，就用最近config.EC1 1的水深
                if self.config.fix[dmnum][i][0] <= self.config.EC1[dmnum][0][0]:
                    ft = self.config.fix[dmnum][i][0]
                    fxh = int(self.config.fix[dmnum][i][1])
                    fz = self.config.EC1[dmnum][0][1]
                # 如果config.fix数据后没有config.EC1 1数据，就用最近config.EC1 1的水深
                elif self.config.fix[dmnum][i][0] >= self.config.EC1[dmnum][len(self.config.EC1[dmnum]) - 1][0]:
                    ft = self.config.fix[dmnum][i][0]
                    fxh = int(self.config.fix[dmnum][i][1])
                    fz = self.config.EC1[dmnum][len(self.config.EC1[dmnum]) - 1][1]
                else:
                    for j in range(1, len(self.config.EC1[dmnum])):
                        if (self.config.fix[dmnum][i][0] >= self.config.EC1[dmnum][j - 1][0]) & (self.config.fix[dmnum][i][0] <= self.config.EC1[dmnum][j][0]):
                            ft = self.config.fix[dmnum][i][0]
                            fxh = int(self.config.fix[dmnum][i][1])
                            fz = self.config.EC1[dmnum][j][1]
            
            # 处理坐标
            for k in range(1, len(self.config.POS[dmnum])):
                 # 如果config.fix数前没有config.POS数据，就用最近config.POS的坐标
                if self.config.fix[dmnum][i][0] <= self.config.POS[dmnum][0][0]:
                    fx = self.config.POS[dmnum][0][1]
                    fy = self.config.POS[dmnum][0][2]
                # 如果config.fix数据后没有config.POS数据，就用最近config.POS的坐标
                elif self.config.fix[dmnum][i][0] >= self.config.POS[dmnum][len(self.config.POS[dmnum]) - 1][0]:
                    fx = self.config.POS[dmnum][len(self.config.POS[dmnum]) - 1][1]
                    fy = self.config.POS[dmnum][len(self.config.POS[dmnum]) - 1][2]
                else:
                    if (self.config.fix[dmnum][i][0] >= self.config.POS[dmnum][k - 1][0]) & (self.config.fix[dmnum][i][0] <= self.config.POS[dmnum][k][0]):
                        t = self.config.POS[dmnum][k][0] - self.config.POS[dmnum][k - 1][0]
                        t1 = self.config.fix[dmnum][i][0] - self.config.POS[dmnum][k - 1][0]
                        fx = round((t1 / t) * (self.config.POS[dmnum][k][1] - self.config.POS[dmnum][k - 1][1]) + self.config.POS[dmnum][k - 1][1], 3)
                        fy = round((t1 / t) * (self.config.POS[dmnum][k][2] - self.config.POS[dmnum][k - 1][2]) + self.config.POS[dmnum][k - 1][2], 3)
            
            result = [ft, fxh, fx, fy, fz]  # 时间、序号、X(E)、Y(N)、Z(水深)
            self.config.FIX[dmnum].append(result)
        
        # 设置加点数据的点号
        if len(self.config.add[dmnum]) == 0:
            self.config.XH[dmnum] = self.config.fix[dmnum][len(self.config.fix[dmnum]) - 1][1]
        else:
            self.config.XH[dmnum] = self.config.add[dmnum][len(self.config.add[dmnum]) - 1][1]
        
        # 转换为DataFrame
        self.config.dfFIX[dmnum] = pd.DataFrame(self.config.FIX[dmnum])
        self.config.dfFIX[dmnum].columns = ['时间', '序号', 'E', 'N', '水深']
        
        if len(self.config.EC1[dmnum]) > 0:
            self.config.dfEC1[dmnum] = pd.DataFrame(self.config.EC1[dmnum])
            self.config.dfEC1[dmnum].columns = ['时间', '水深']
        
        self.config.ZZFIX[dmnum] = self.config.dfFIX[dmnum]
        self.config.ys_ZZFIX[dmnum] = self.config.ZZFIX[dmnum]

    def _process_add_points(self):
        """处理加点数据"""
        dmnum = self.config.dmnum
        
        if self.config.ytfx[dmnum] == 0 and len(self.config.add[dmnum]) != 0:
            for i in range(len(self.config.add[dmnum])):
                if self.config.add[dmnum][i][0] < self.config.EC1[dmnum][0][0]:
                    continue
                if self.config.add[dmnum][i][0] > self.config.EC1[dmnum][len(self.config.EC1[dmnum]) - 1][0]:
                    continue
                
                # 处理水深
                for j in range(len(self.config.EC1[dmnum])):
                    if (self.config.add[dmnum][i][0] >= self.config.EC1[dmnum][j - 1][0]) & (self.config.add[dmnum][i][0] <= self.config.EC1[dmnum][j][0]):
                        ft = self.config.add[dmnum][i][0]
                        fxh = int(self.config.add[dmnum][i][1])
                        fz = self.config.EC1[dmnum][j][1]
                
                # 处理坐标
                for k in range(len(self.config.POS[dmnum])):
                    if (self.config.add[dmnum][i][0] >= self.config.POS[dmnum][k - 1][0]) & (self.config.add[dmnum][i][0] <= self.config.POS[dmnum][k][0]):
                        T = self.config.POS[dmnum][k][0] - self.config.POS[dmnum][k - 1][0]
                        T1 = self.config.add[dmnum][i][0] - self.config.POS[dmnum][k - 1][0]
                        fx = round((T1 / T) * (self.config.POS[dmnum][k][1] - self.config.POS[dmnum][k - 1][1]) + self.config.POS[dmnum][k - 1][1], 3)
                        fy = round((T1 / T) * (self.config.POS[dmnum][k][2] - self.config.POS[dmnum][k - 1][2]) + self.config.POS[dmnum][k - 1][2], 3)
                
                result = [ft, fxh, fx, fy, fz]  #时间、序号、Y(E),X(N)，Z(水深)
                self.config.ADD[dmnum].append(result)
            
            # 转换为DataFrame
            if self.config.ADD[dmnum]:
                self.config.dfADD[dmnum] = pd.DataFrame(self.config.ADD[dmnum])
                self.config.dfADD[dmnum].columns = ['时间', '序号', 'E', 'N', '水深']
                
                if not self.config.dfADD[dmnum].empty:
                    # 替换append为concat
                    self.config.ZZFIX[dmnum] = pd.concat([self.config.ZZFIX[dmnum], self.config.dfADD[dmnum]])
                    self.config.ZZFIX[dmnum] = self.config.ZZFIX[dmnum].sort_values(by=['时间'])
                    self.config.ZZFIX[dmnum] = self.config.ZZFIX[dmnum].reset_index(drop=True)

    def _process_change_points(self):
        """处理改点数据（与原始代码完全一致）"""
        dmnum = self.config.dmnum
        
        if self.config.ytfx[dmnum] == 0 and len(self.config.CHA[dmnum]) != 0:
            self.config.dfCHA[dmnum] = pd.DataFrame(self.config.CHA[dmnum])
            self.config.dfCHA[dmnum].columns = ['时间', '序号', '原始水深', '改正水深']
            
            for i in range(len(self.config.CHA[dmnum])):
                # 更新ZZFIX
                mask = self.config.ZZFIX[dmnum]['时间'] == self.config.CHA[dmnum][i][0]
                self.config.ZZFIX[dmnum].loc[mask, '水深'] = self.config.CHA[dmnum][i][3]
                
                # 更新dfFIX
                if not self.config.dfFIX[dmnum].empty:
                    mask = self.config.dfFIX[dmnum]['时间'] == self.config.CHA[dmnum][i][0]
                    self.config.dfFIX[dmnum].loc[mask, '水深'] = self.config.CHA[dmnum][i][3]
                
                # 更新dfADD
                if not self.config.dfADD[dmnum].empty:
                    mask = self.config.dfADD[dmnum]['时间'] == self.config.CHA[dmnum][i][0]
                    self.config.dfADD[dmnum].loc[mask, '水深'] = self.config.CHA[dmnum][i][3]

    def _process_delete_points(self):
        """处理删点数据"""
        dmnum = self.config.dmnum
        
        if self.config.ytfx[dmnum] == 0:
            # 收集删点数据
            if len(self.config.ysdel[dmnum]) != 0:
                for i in range(len(self.config.ysdel[dmnum])):
                    mask = self.config.ZZFIX[dmnum]['时间'] == self.config.ysdel[dmnum][i][0]
                    if self.config.dfDEL[dmnum].empty:
                        self.config.dfDEL[dmnum] = self.config.ZZFIX[dmnum][mask]
                    else:
                        # 替换append为concat
                        self.config.dfDEL[dmnum] = pd.concat([self.config.dfDEL[dmnum], self.config.ZZFIX[dmnum][mask]])
            
            # 处理删点
            if not self.config.dfDEL[dmnum].empty:
                # 更新ZZFIX
                self.config.ZZFIX[dmnum] = pd.concat([self.config.ZZFIX[dmnum], self.config.dfDEL[dmnum]])
                self.config.ZZFIX[dmnum] = pd.concat([self.config.ZZFIX[dmnum], self.config.dfDEL[dmnum]])
                self.config.ZZFIX[dmnum] = self.config.ZZFIX[dmnum].drop_duplicates(keep=False)
                self.config.ZZFIX[dmnum] = self.config.ZZFIX[dmnum].reset_index(drop=True)
                
                # 更新dfFIX
                self.config.dfFIX[dmnum] = pd.concat([self.config.dfFIX[dmnum], self.config.dfDEL[dmnum]])
                self.config.dfFIX[dmnum] = pd.concat([self.config.dfFIX[dmnum], self.config.dfDEL[dmnum]])
                self.config.dfFIX[dmnum] = self.config.dfFIX[dmnum].drop_duplicates(keep=False)
                self.config.dfFIX[dmnum] = self.config.dfFIX[dmnum].reset_index(drop=True)
                
                # 更新dfADD
                if not self.config.dfADD[dmnum].empty:
                    self.config.dfADD[dmnum] = pd.concat([self.config.dfADD[dmnum], self.config.dfDEL[dmnum]])
                    self.config.dfADD[dmnum] = pd.concat([self.config.dfADD[dmnum], self.config.dfDEL[dmnum]])
                    self.config.dfADD[dmnum] = self.config.dfADD[dmnum].drop_duplicates(keep=False)
                    self.config.dfADD[dmnum] = self.config.dfADD[dmnum].reset_index(drop=True)
                    
                    # 从ADD列表中删除对应的点
                    temp = []
                    for i in range(len(self.config.ADD[dmnum])):
                        for j in range(len(self.config.ysdel[dmnum])):
                            if self.config.ADD[dmnum][i][0] == self.config.ysdel[dmnum][j][0]:
                                temp.append(i)
                    
                    if temp:
                        t1 = 0
                        for i in temp:
                            t = i - t1
                            self.config.ADD[dmnum].pop(t)
                            t1 += 1
                
                # 清空dfDEL
                self.config.dfDEL[dmnum] = self.config.dfDEL[dmnum].drop(index=self.config.dfDEL[dmnum].index)

    def _merge_ec1_and_pos_data(self):
        """
        将EC1高程数据与POS坐标数据根据时间戳进行拼接
        利用EC1和POS数据均已按时间升序排列的特性，使用双指针技术优化匹配算法
        时间复杂度从O(n*m)降低到O(n+m)
        """
        dmnum = self.config.dmnum
        
        # 检查数据是否存在
        if len(self.config.EC1[dmnum]) == 0 or len(self.config.POS[dmnum]) == 0:
            print(f"警告: EC1或POS数据为空，无法进行数据拼接")
            return []
        
        merged_data = []
        # 最大时间差限制（秒），可以根据需要调整
        max_time_difference = 2.0  # 设定的时间限制
        
        # 双指针实现，利用数据已排序的特性
        pos_idx = 0  # POS数据的当前指针位置
        ec1_len = len(self.config.EC1[dmnum])
        pos_len = len(self.config.POS[dmnum])
        
        # 遍历EC1数据
        for ec1_idx in range(ec1_len):
            ec1_point = self.config.EC1[dmnum][ec1_idx]
            ec1_time = ec1_point[0]  # EC1时间戳
            ec1_depth = ec1_point[1]  # 水深/高程
            
            # 初始化匹配标志和最佳匹配
            best_pos_point = None
            min_abs_time_diff = float('inf')
            
            # 由于数据已排序，我们只需要从当前pos_idx开始查找
            # 首先移动pos_idx到可能的起始位置（POS时间不早于EC1时间减去max_time_difference）
            while (pos_idx < pos_len - 1 and 
                  self.config.POS[dmnum][pos_idx][0] < ec1_time - max_time_difference):
                pos_idx += 1
            
            # 检查当前位置及其后续几个位置（因为数据已排序，超出max_time_difference后可以停止）
            temp_idx = pos_idx
            while temp_idx < pos_len:
                pos_point = self.config.POS[dmnum][temp_idx]
                pos_time = pos_point[0]
                
                # 如果POS时间已经超过EC1时间+max_time_difference，可以提前退出循环
                if pos_time > ec1_time + max_time_difference:
                    break
                
                # 计算时间差绝对值
                abs_time_diff = abs(pos_time - ec1_time)
                
                # 如果在时间限制内
                if abs_time_diff <= max_time_difference:
                    if abs_time_diff < min_abs_time_diff:
                        min_abs_time_diff = abs_time_diff
                        best_pos_point = pos_point
                
                temp_idx += 1
            
            # 如果找到匹配的POS点，添加到合并数据中
            if best_pos_point:
                pos_e = best_pos_point[1]
                pos_n = best_pos_point[2]
                merged_data.append([ec1_time, pos_e, pos_n, ec1_depth])
        
        # 将合并数据存储到config对象中
        if merged_data:
            # 确保config对象有merged_ec1_pos属性
            if not hasattr(self.config, 'merged_ec1_pos'):
                self.config.merged_ec1_pos = None
            # 转换为DataFrame
            self.config.merged_ec1_pos = pd.DataFrame(merged_data)
            self.config.merged_ec1_pos.columns = ['时间', 'E', 'N', '水深']
        
        matched_count = len(merged_data)
        unmatched_count = ec1_len - matched_count
        print(f"EC1与POS数据匹配完成: 匹配成功 {matched_count} 个，未匹配 {unmatched_count} 个，EC1总点数: {ec1_len}")
        return merged_data

    def _prepare_output(self):
        """准备输出数据"""
       
        # 不需要返回具体值，因为数据已存储在config对象中
        return True